﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;

namespace HomeFramework.Services
{
    public class HomeFrameworkRouterMessageInspector : IDispatchMessageInspector
    {
        public const string HEADER_NAMESPACE = "http://hf.dotnetlombardia.org";

        public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
        {
            if (!request.IsEmpty)
            {
                var query = Query(request.Headers.To.Query);

                if (!query.ContainsKey("name"))
                    throw new ArgumentException("name query parameter not specified!");

                var buffer = request.CreateBufferedCopy(int.MaxValue);
                var message = buffer.CreateMessage();
                var path = request.Headers.To.AbsolutePath;
                var scheme = request.Headers.To.Scheme;

                var endpoint = instanceContext.Host.Description.Endpoints.SingleOrDefault(
                   x => x.Address.Uri.AbsolutePath == path & x.Address.Uri.Scheme == scheme);

                if (endpoint == null)
                    throw new ArgumentException("Unable to find the selected endpoint!");

                message.Headers.Add(MessageHeader.CreateHeader("path", "http://hf.dotnetlombardia.org", path));
                message.Headers.Add(MessageHeader.CreateHeader("scheme", "http://hf.dotnetlombardia.org", scheme));
                message.Headers.Add(MessageHeader.CreateHeader("binding", "http://hf.dotnetlombardia.org", endpoint.Binding.GetType().FullName));

                foreach (var v in Query(request.Headers.To.Query))
                    message.Headers.Add(MessageHeader.CreateHeader(v.Key, "http://hf.dotnetlombardia.org", v.Value));

                request = message;
                return null;
            }
            else
                return request.Headers.To;
        }

        public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            if (correlationState != null && correlationState is Uri)
            {
                var to = (Uri)correlationState;
                if (!string.IsNullOrEmpty(to.Query))
                {
                    var query = Query(to.Query);
                    Version version;

                    if (!Version.TryParse((query.ContainsKey("version") ? query["version"] : string.Empty), out version))
                        version = new Version("1.0.0.0");

                    var baseAddress = to.AbsoluteUri.Replace(to.Query, "");
                    if (query.ContainsKey("wsdl"))
                        reply = HomeFrameworkEngine.WsdlGenerator.GenerateWsdl(query["wsdl"], version.ToString(), baseAddress);
                    else if (query.ContainsKey("help"))
                        reply = HomeFrameworkEngine.HelpPageGenerator.GenerateHelpPage(query["help"], version.ToString(), reply, baseAddress);
                }
            }
        }

        private Dictionary<string, string> Query(string arg)
        {
            var risp = new Dictionary<string, string>();
            foreach (var s in arg.TrimStart('?').Split('&'))
            {
                var split = s.Split('=');
                if (split.Length == 2)
                    risp.Add(s.Split('=')[0].ToLower(), s.Split('=')[1]);
            }
            return risp;
        }
    }
}